##############################################################################
# andy6th.py $Rev: 14:2a1113a6efc1 $
# $Id: testusbserial.py 14:2a1113a6efc1 2012/08/20 22:40:12 shimoda $
# $URL: https://android-jp-kobe.googlecode.com/svn/trunk/pyAndyUI/uibt2.py $
#
# Copyright (c) 2012, shimoda as kuri65536 _dot_ hot mail _dot_ com
#                       ( email address: convert _dot_ to . and joint string )
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted
# provided that the following conditions are met:
#
# - Redistributions of source code must retain the above copyright notice, this list of conditions and
#   the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice, this list of conditions
#   and the following disclaimer in the documentation and/or other materials provided with the
#   distribution.
# - Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or
#   promote products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##############################################################################
import sys
import time
import json
import android
try:
    from fullscreenwrapper2 import Layout, \
            click_EventHandler, \
            click_EventHandler, \
            itemclick_EventHandler, \
            FullScreenWrapper2App as app
except ImportError:
    from fullscreenwrapper2_py3 import Layout, \
            click_EventHandler, \
            itemclick_EventHandler, \
            FullScreenWrapper2App as app


xmldata = """<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TextView
            android:id="@+id/textView1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Motor"
            android:background="#000000"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    <SeekBar
            android:id="@+id/sbar_motor"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="510"
            android:progress="256"
            android:padding="30dip"
            />
    <TextView
            android:id="@+id/textView2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Gauge"
            android:background="#000000"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    <SeekBar
            android:id="@+id/sbar_gauge"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="128"
            android:padding="30dip"
            />
    <TextView
            android:id="@+id/textView3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="LED"
            android:background="#000000"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    <SeekBar
            android:id="@+id/sbar_led"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="100"
            android:padding="30dip"
            />
    <Button
            android:id="@+id/but_misc"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="???"
            />
    <Button
            android:id="@+id/but_quit"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Quit"
            />
</LinearLayout>"""


class Andy6CtrlLayout(Layout):
    def __init__(self, uuid):
        super(Andy6CtrlLayout, self). \
            __init__(xmldata, "Andy6th Contoller")

        # parameters
        self.motor = 0
        self.led = 0
        self.gauge = 0
        self.uuid = uuid
        self.tbase = time.time()

    def on_show(self):
        self.views.sbar_motor.add_event(itemclick_EventHandler(
            self.views.sbar_motor, handler_function=self.onMotor))
        self.views.sbar_gauge.add_event(itemclick_EventHandler(
            self.views.sbar_gauge, handler_function=self.onGauge))
        self.views.sbar_led.add_event(itemclick_EventHandler(
            self.views.sbar_led, handler_function=self.onLED))
        self.views.but_misc.add_event(click_EventHandler(
            self.views.but_misc, self.onMisc))
        self.views.but_quit.add_event(click_EventHandler(
            self.views.but_quit, self.onQuit))

    def on_close(self):
        pass

    def onQuit(self, view, event):
        app.exit_FullScreenWrapper2App()
        droid.usbserialWrite("F000F000", uuid)      # stop to contorl

    def onMisc(self, view, event):
        cur = self.operation(misc=True)

    def onMotor(self, view, event):
        speed = event["data"]["position"]
        speed = int(speed) - 255
        cur = self.operation(motor=speed)

    def onGauge(self, view, event):
        slotle = event["data"]["position"]
        slotle = int(slotle)
        cur = self.operation(gauge=slotle)

    def onLED(self, view, event):
        brightness = event["data"]["position"]
        brightness = int(brightness)
        cur = self.operation(led=brightness)

    def operation(self, motor=None, led=None, gauge=None, misc=None):   # {{{1
        # 1st, set motor speed.
        if motor is None:
            motor = self.motor
        if motor < 0:
            if motor < -255:
                motor = -255
            ret = "B%03d" % (-motor)
        else:
            if motor > 255:
                motor = 255
            ret = "F%03d" % motor
        self.motor = motor

        # 2nd, set various equipments.
        if led is not None:
            self.led = led = led % 256          # limit and force positive
            ret += "F%03d" % led
        elif gauge is not None:
            self.gauge = gauge = gauge % 256    # limit and force positive
            ret += "B%03d" % gauge
        elif misc is not None:
            if misc:
                ret += "S255"
            else:
                ret += "S000"
            self.misc = not (not misc)
        else:
            ret += "B%03d" % self.gauge

        if droid.usbserialReadReady(uuid).result:
            buf = droid.usbserialRead(uuid)
            print("Received: ", buf)

        t = time.time()
        if t - self.tbase > 0.3:
            print("send bytes...", ret)
            self.tbase = t
            droid.usbserialWrite(ret, uuid)
        return ret


def connect():     #{{{1
    h = None
    for k, v in droid.usbserialGetDeviceList().result.items():
        print(k, v)
        if '"0409","FFFD"' in v:
            # v is '["device-name","VID","PID","hashCode"]'
            h = json.loads(v)[-1]
            print("device was found, try to connect =>", h)
    if h is None:
        print("device was not found")
        return False

    ret = droid.usbserialConnect(h)
    if not "OK" in ret.result:
        print("can't connect to device: ", ret.result)
        return False
    uuid = json.loads(ret.result)[-1]
    print("connected with ", h, uuid)

    # wait until the permission be allowed by user.
    n = 10
    while n > 0 and not droid.usbserialReadReady(uuid).result:
        n -= 1
        print("waiting for connect....", n)
        time.sleep(1)

    if n <= 0:
        print("??? can't receive start byte ???")
        return False
    return uuid


if __name__ == '__main__':
    droid = android.Android()
    uuid = connect()
    if 1 and not uuid:
        droid.makeToast("can't connect to USB Serial!")
        sys.exit(0)
    app.initialize(droid)
    app.show_layout(Andy6CtrlLayout(uuid))
    app.eventloop()

# vi: ft=python:ts=4:et
